package com.ruoyi.data.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.helper.LoginHelper;
import com.ruoyi.common.utils.StreamUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.core.domain.PageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.ruoyi.common.utils.redis.RedisUtils;
import com.ruoyi.data.domain.DataClassificationUser;
import com.ruoyi.data.domain.DataList;
import com.ruoyi.data.mapper.DataClassificationUserMapper;
import com.ruoyi.data.mapper.DataListMapper;
import lombok.RequiredArgsConstructor;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import com.ruoyi.data.domain.bo.DataClassificationBo;
import com.ruoyi.data.domain.vo.DataClassificationVo;
import com.ruoyi.data.domain.DataClassification;
import com.ruoyi.data.mapper.DataClassificationMapper;
import com.ruoyi.data.service.IDataClassificationService;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 分类管理Service业务层处理
 *
 * @author ruoyi
 * @date 2023-10-26
 */
@RequiredArgsConstructor
@Service
public class DataClassificationServiceImpl implements IDataClassificationService {

    private final DataClassificationMapper baseMapper;
    private final DataClassificationUserMapper dataClassificationUserMapper;
    private final DataListMapper dataListMapper;

    /**
     * 查询分类管理
     */
    @Override
    public DataClassification queryById(Long classificationId){
        DataClassification dataClassification = baseMapper.selectById(classificationId);
        if (ObjectUtil.isNotNull(dataClassification)){
            dataClassification.setDataClassificationUserList(
                dataClassificationUserMapper.selectList(
                    new LambdaQueryWrapper<DataClassificationUser>()
                        .eq(DataClassificationUser::getClassificationId, classificationId)
                )
            );
        }

        return dataClassification;
    }

    /**
     * 查询分类管理列表
     */
    @Override
    public TableDataInfo<DataClassification> queryPageList(DataClassificationBo bo, PageQuery pageQuery) {
        QueryWrapper<DataClassification> lqw = buildQueryWrapper(bo);
        Page<DataClassification> result = baseMapper.selectDataClassificationVoPage(pageQuery.build(), lqw);

        for (DataClassification d : result.getRecords()){
            d.setDataClassificationUserList(dataClassificationUserMapper.selectDataClassificationUserList(d.getClassificationId()));
        }

        return TableDataInfo.build(result);
    }

    /**
     * 查询分类管理列表
     */
    @Override
    public List<DataClassificationVo> queryList(DataClassificationBo bo) {
        RedissonClient client = RedisUtils.getClient();

        List<DataClassificationVo> dataClassificationVos = null;

        Long userId = LoginHelper.getUserId();
        //管理员查全部
        if (LoginHelper.isAdmin()){
            QueryWrapper<DataClassification> lqw = buildQueryWrapper2(bo);
            dataClassificationVos = baseMapper.selectVoList(lqw);
        } else {
            dataClassificationVos = baseMapper.selectClassificationByIdUserId(userId, bo);
        }

        //查询数量
        dataClassificationVos.forEach(dataClassificationVo -> {
            LambdaQueryWrapper<DataList> dataListLqw = Wrappers.lambdaQuery();

            dataListLqw.eq(DataList::getClassificationId, dataClassificationVo.getClassificationId());
            dataListLqw.eq(StringUtils.isNotBlank(bo.getStatus()), DataList::getStatus, bo.getStatus());
            dataListLqw.eq(!LoginHelper.isAdmin(), DataList::getUserId, userId);

            dataClassificationVo.setCount(dataListMapper.selectCount(dataListLqw));

            LambdaQueryWrapper<DataList> dataListLqw1 = Wrappers.lambdaQuery();

            dataListLqw1.eq(DataList::getClassificationId, dataClassificationVo.getClassificationId());
            dataListLqw1.eq(StringUtils.isNotBlank(bo.getStatus()), DataList::getStatus, bo.getStatus());
            dataListLqw1.eq(!LoginHelper.isAdmin(), DataList::getUserId, userId);
            dataListLqw1.eq(DataList::getCacheType, 1);

            dataClassificationVo.setCacheCount(dataListMapper.selectCount(dataListLqw1));
        });

        return dataClassificationVos;
    }

    private QueryWrapper<DataClassification> buildQueryWrapper(DataClassificationBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<DataClassification> lqw = Wrappers.query();
        lqw.like(StringUtils.isNotBlank(bo.getClassificationName()), "dc.classification_name", bo.getClassificationName());
        lqw.eq(StringUtils.isNotBlank(bo.getTableHead()), "dc.table_head", bo.getTableHead());
        lqw.eq(StringUtils.isNotBlank(bo.getClassificationType()), "dc.classification_type", bo.getClassificationType());
//        lqw.eq(StringUtils.isNotBlank(bo.getDelFlag()), "dc.del_flag", bo.getDelFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getUserId()), "dcu.user_id", bo.getUserId());
        lqw.eq( "dc.del_flag", "0");

        return lqw;
    }

    private QueryWrapper<DataClassification> buildQueryWrapper2(DataClassificationBo bo) {
        Map<String, Object> params = bo.getParams();
        QueryWrapper<DataClassification> lqw = Wrappers.query();
        lqw.like(StringUtils.isNotBlank(bo.getClassificationName()), "dc.classification_name", bo.getClassificationName());
        lqw.eq(StringUtils.isNotBlank(bo.getTableHead()), "dc.table_head", bo.getTableHead());
        lqw.eq(StringUtils.isNotBlank(bo.getClassificationType()), "dc.classification_type", bo.getClassificationType());
//        lqw.eq(StringUtils.isNotBlank(bo.getDelFlag()), "dc.del_flag", bo.getDelFlag());
        lqw.eq(StringUtils.isNotBlank(bo.getUserId()), "dcu.user_id", bo.getUserId());

        return lqw;
    }

    /**
     * 新增分类管理
     * 如果分类主表不存在则新增
     */
    @Override
    @Transactional
    public Boolean insertByBo(DataClassificationBo bo, Long userId) {
        DataClassification add = BeanUtil.toBean(bo, DataClassification.class);
        add.setUserId(userId);

        boolean flag;
        DataClassification dataClassification = validEntityBeforeSave(add);
        //如果分类不存在
        if (dataClassification == null){
            flag = baseMapper.insert(add) > 0;
            if (flag) {
                bo.setClassificationId(add.getClassificationId());
            }
            dataClassification = add;
        }
        // 校验子表是否存在
        else {
            Long c = dataClassificationUserMapper.selectCount(
                new LambdaQueryWrapper<DataClassificationUser>()
                    .eq(DataClassificationUser::getClassificationId, dataClassification.getClassificationId())
                    .eq(DataClassificationUser::getUserId, userId)
            );
            if (c > 0){
                throw new ServiceException("分类已存在");
            }
        }
        //加子表
        DataClassificationUser dataClassificationUser = new DataClassificationUser();
        dataClassificationUser.setUserId(userId);
        dataClassificationUser.setClassificationId(dataClassification.getClassificationId());
        flag = dataClassificationUserMapper.insert(dataClassificationUser) > 0;

        return flag;
    }

    /**
     * 修改分类管理
     */
    @Override
    public Boolean updateByBo(DataClassificationBo bo) {
        DataClassification update = BeanUtil.toBean(bo, DataClassification.class);
        DataClassification dataClassification = validEntityBeforeSave(update);



        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     * 校验当前用户下分类主表是否存在
     */
    private DataClassification validEntityBeforeSave(DataClassification entity){
        //校验 当前用户的未删除分类是否存在
        return baseMapper.selectDataClassificationByValidEntityBeforeSave(entity.getClassificationName(), entity.getClassificationType(), LoginHelper.getUserId());

    }

    /**
     * 批量删除分类管理
     */
    @Override
    @Transactional
    public Boolean deleteWithValidByIds(Long userId, Collection<Long> ids, Boolean isValid) {

        List<Long> dIds = new ArrayList<>(), uIds = new ArrayList<>();

        for (Long id : ids){
            List<DataClassification> list = baseMapper.selectList(new LambdaQueryWrapper<DataClassification>()
                .select(DataClassification::getClassificationId)
                .eq(!LoginHelper.isAdmin(), DataClassification::getUserId, userId)
                .eq(DataClassification::getClassificationId, id)
            );

            List<Long> collect = list.stream().map(DataClassification::getClassificationId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(collect)){
                dIds.addAll(collect);
            }
        }

        for (Long id : ids){
            List<DataClassificationUser> dataClassificationUsers = dataClassificationUserMapper.selectList(new LambdaQueryWrapper<DataClassificationUser>()
                .select(DataClassificationUser::getClassificationUserId)
                .eq(!LoginHelper.isAdmin(), DataClassificationUser::getUserId, userId)
                .eq(DataClassificationUser::getClassificationId, id)
            );

            List<Long> collect = dataClassificationUsers.stream().map(DataClassificationUser::getClassificationUserId).collect(Collectors.toList());

            if (CollUtil.isNotEmpty(collect)) {
                uIds.addAll(collect);
            }
        }

        //逻辑删除
        if (CollUtil.isNotEmpty(dIds)) {
            baseMapper.deleteBatchIds(dIds);
        }
        return dataClassificationUserMapper.deleteBatchIds(uIds) > 0;

    }

    @Override
    public List<DataClassificationVo> selectClassificationByIdUserId(Long userId, DataClassificationBo bo) {

        return baseMapper.selectClassificationByIdUserId(userId, bo);
    }

    @Override
    public Boolean deleteDataClassificationByUserId(Long userId, String classificationType) {

        DataClassificationBo d = new DataClassificationBo();
        d.setClassificationType(classificationType);

        return baseMapper.deleteDataClassificationByUserId(userId, d);
    }

    @Override
    public void insertDataClassificationUser(Long userId, Long[] classificationIds) {
        if (ArrayUtil.isNotEmpty(classificationIds)) {
            // 新增用户与分类
            List<DataClassificationUser> list = StreamUtils.toList(Arrays.asList(classificationIds), cId -> {
                DataClassificationUser up = new DataClassificationUser();
                up.setUserId(userId);
                up.setClassificationId(cId);
                return up;
            });
            dataClassificationUserMapper.insertBatch(list);
        }
    }

    @Override
    @Transactional
    public boolean checkClassificationUnique(Long[] classificationIds, Long userId) {

        //查询当前用户已经有的分类id
        List<DataClassificationUser> dataClassificationUsers = dataClassificationUserMapper.selectList(
            new LambdaQueryWrapper<DataClassificationUser>()
                .select(DataClassificationUser::getClassificationId)
                .eq(DataClassificationUser::getUserId, userId)
                .groupBy(DataClassificationUser::getClassificationId)
        );

        //获得差集不能有重名的数据
        if (CollUtil.isNotEmpty(dataClassificationUsers)){
            List<Long> nowList = dataClassificationUsers.stream().map(DataClassificationUser::getClassificationId).collect(Collectors.toList());
            List<Long> collect = Arrays.asList(classificationIds).stream()
                .filter(element -> !nowList.contains(element))
                .collect(Collectors.toList());

            for (Long id : collect){

                DataClassification dataClassification = baseMapper.selectById(id);

                DataClassificationBo bo = new DataClassificationBo();
                bo.setClassificationName(dataClassification.getClassificationName());
                List<DataClassificationVo> dataClassificationVos = baseMapper.selectClassificationByIdUserId(userId, bo);

                if (CollUtil.isNotEmpty(dataClassificationVos)){
                    return true;
                }
            }
        }
        return false;
    }

    @Override
    @Transactional
    public int editDataClassificationUser(DataClassificationBo bo) {
        List<Long> editUserIds = bo.getEditUserIds();
        List<DataClassificationUser> iData= new ArrayList<>();

        if (CollUtil.isNotEmpty(editUserIds)){
            List<DataClassificationUser> dataClassificationUsers = dataClassificationUserMapper.selectList(
                new LambdaQueryWrapper<DataClassificationUser>()
                    .eq(DataClassificationUser::getClassificationId, bo.getClassificationId())
                    .eq(!LoginHelper.isAdmin(), DataClassificationUser::getUserId, LoginHelper.getUserId()));

            List<Long> delList = dataClassificationUsers.stream().map(DataClassificationUser::getClassificationId).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(delList))
            dataClassificationUserMapper.physicsDeleteBatchIds(delList);

            for (Long userId : editUserIds){
                DataClassificationUser d = new DataClassificationUser();
                d.setClassificationId(bo.getClassificationId());

                List<DataClassificationUser> collect = dataClassificationUsers.stream().filter(data-> userId == data.getUserId()).collect(Collectors.toList());
                if (CollUtil.isNotEmpty(collect)){
                    d.setUserId(collect.get(0).getUserId());
                } else {
                    d.setUserId(userId);
                }

                iData.add(d);

            }
            boolean b = dataClassificationUserMapper.insertBatch(iData);
            return 1;
        }
        return 0;
    }
}
